﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using ZenSystemService.Api.Data;
using ZenSystemService.Api.DTOs;
using ZenSystemService.Api.DTOs.Legency;
using ZenSystemService.Api.DTOs.ProductType;
using ZenSystemService.Api.DTOs.TrainingItem;
using ZenSystemService.Api.DTOs.TrainingReport;
using ZenSystemService.Api.DTOs.Users;
using ZenSystemService.Api.Entities;
using ZenSystemService.Api.Utils;

namespace ZenSystemService.Api.Services
{
    public class TrainingReportService
    {
        private readonly ApplicationDbContext _context;
        private readonly IMapper _mapper;
        private readonly ZenBrightService _zenBrightService;
        private readonly IConfiguration _configuration;

        public TrainingReportService(ApplicationDbContext context, IMapper mapper, 
            ZenBrightService zenBrightService, IConfiguration configuration)
        {
            _context = context;
            _mapper = mapper;
            _zenBrightService = zenBrightService;
            _configuration = configuration;
        }

        public async Task<ReturnObjectT<IEnumerable<TrainingReportQueryResultDTO>>> GetTrainingReportsAsync(
            ReceiveObject req)
        {
            string orderBy = req.Order;
            var splited = orderBy.Split(' ');
            var orderField = "";
            var orderMethod = "";
            if (splited.Length > 0)
            {
                orderField = $"{splited[0]}";
            }
            if (splited.Length > 1)
            {
                orderMethod = splited[1];
            }

            var trainingReportsPagedResult = _context.TrainingReports.Include(o => o.Trainee)
                .Include(o => o.Course)
                .Include(o => o.TrainingItem)
                .AsQueryable();

            trainingReportsPagedResult = trainingReportsPagedResult.FilterByString(req.Where);
            //int totalCount = trainingReportsPagedResult.Count();
            int index = (req.Page < 0 ? 0 : req.Page - 1) * req.PageSize;
            //trainingReportsPagedResult = trainingReportsPagedResult.Skip(index).Take(req.PageSize);

            var totalCount = 0;
            

            var traingReportsDTO = _mapper.Map<IEnumerable<TrainingReportQueryResultDTO>>(
                trainingReportsPagedResult.ToList());

            
            var legencyUserId = await GetLegencyUserIdAsync(req.Where);
            //如果查询条件里面包含了TraineeId，这需要查询对应的User的ZenBright report就可以了
            if (legencyUserId > 0)
            {
                var zenBrightReports = await GetZenBrightReportsAsync(5331);
                traingReportsDTO = traingReportsDTO.Union(zenBrightReports);
            }
            else
            {
                //否则，需要先根据
            }
            return new ReturnObjectT<IEnumerable<TrainingReportQueryResultDTO>>
            {
                Code = 1,
                ErrorMsg = "",
                RecordTotalCount = totalCount,
                Data = traingReportsDTO
            };
        }

        public async Task<ReturnObjectT<IEnumerable<TrainingReportQueryResultDTO>>> GetTrainingReportsAsync(
            ReceiveObjectT<TrainingReportQueryRequestDTO> req)
        {
            var query = _context.TrainingReports.Include(tr => tr.Trainee)
                .Include(tr => tr.Course)
                .Include(tr => tr.TrainingItem).AsQueryable();

            if(req.Data != null)
            {
                if(req.Data.TraineeId != null && req.Data.TraineeId > 0)
                    query = query.Where(q => q.TraineeId == req.Data.TraineeId);
                if(req.Data.CourseId != null && req.Data.CourseId > 0)
                    query = query.Where(q => q.CourseId == req.Data.CourseId);
                if (req.Data.TrainingItemId != null && req.Data.TrainingItemId > 0)
                    query = query.Where(q => q.TrainingItemId == req.Data.TrainingItemId);
            }

            var totalRecords = query.Count();
            var pagedReports = query.Skip((req.Page - 1) * req.PageSize).Take(req.PageSize);
            var reportListResult = _mapper.Map<IEnumerable<TrainingReportQueryResultDTO>>(pagedReports);
            return new ReturnObjectT<IEnumerable<TrainingReportQueryResultDTO>>
            {
                Code = 1,
                ErrorMsg = "",
                RecordTotalCount = totalRecords,
                Data = reportListResult
            };
        }

        public async Task<ReturnObjectT<ZenBrightReportFacadeDTO>> GetZenBrightReportsAsync(
            ReceiveObjectT<ZenBrightReportQueryRequestDTO> req)
        {
            var trainee = await _context.Users.FirstOrDefaultAsync(u => u.UserId == req.Data.TraineeId);
            if (trainee == null)
                throw new Exception("找不到学员信息");
            var traineeDTO = _mapper.Map<UserQueryResultDTO>(trainee);
            var legencyUserId = await _context.LegencyUserZenUsers.FirstOrDefaultAsync(lz => lz.ZenUserId == req.Data.TraineeId);
            if (legencyUserId == null)
                throw new Exception("根据Zen System UserId找不到Zen Bright UserId");
            const string endpoint = "/api/ZenSystem/GetOrderResultByUser";
            var request = new ZenBrightReportRequestDTO
            {
                Page = req.Page,
                Rows = req.PageSize,
                Uid = legencyUserId.LegencyUserId 
            };
            var response = await _zenBrightService.GetZenBrightReportAsync(endpoint, request);
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                var zenBrightReports = JsonConvert.DeserializeObject<ZenBrightReportResponseDTO>(json);
                if (zenBrightReports.Data == null || zenBrightReports.Data.Rows.Count == 0)
                    return null;

                
                var reportRows = zenBrightReports.Data.Rows.Select(r =>
                    new ZenBrightReportRowFacadeDTO
                    {
                        Code = r.Code,
                        OrderStep = r.OrderStep,
                        OrderFinishDate = r.OrderFinishDate,
                        JsonData = JsonConvert.SerializeObject(r.TestRecords),
                    }).OrderByDescending(r => r.OrderFinishDate);
                
                return new ReturnObjectT<ZenBrightReportFacadeDTO>
                {
                    Code = 1,
                    ErrorMsg = string.Empty,
                    RecordTotalCount = zenBrightReports.Data.Total,
                    Data = new ZenBrightReportFacadeDTO
                    {
                        ReportRows = reportRows?.ToList(),
                        Trainee = traineeDTO
                    }
                };
            }
            return null;
        }

        private async Task<int> GetLegencyUserIdAsync(string where)
        {
            int traineeId = 0;
            if (string.IsNullOrEmpty(where))
                return 0;
            var traineeIdIndex = where.IndexOf("TraineeId=");
            if (traineeIdIndex >= 0)
            {
                //TraineeId条件只有没有别的条件了
                var traineeIdValueIndex = traineeIdIndex + "TraineeId=".Length;

                if (where.Substring(traineeIdValueIndex).IndexOf("&") < 0)
                {
                    traineeId = int.Parse(where.Substring(traineeIdValueIndex));
                }
                else
                {
                    //TraineeId条件之后还有条件
                    var nextAndIndex = where.Substring(traineeIdValueIndex).IndexOf("&");
                    
                    traineeId = int.Parse(where.Substring(traineeIdValueIndex, nextAndIndex));
                }
            }
            if (traineeId > 0)
            {
                var legencyUser = await _context.LegencyUserZenUsers.FirstOrDefaultAsync(lz => lz.ZenUserId == traineeId);
                if (legencyUser == null)
                    return 0;
                return legencyUser.LegencyUserZenUserId;
            }
            return 0;
        }

        private async Task<IEnumerable<TrainingReportQueryResultDTO>> GetZenBrightReportsAsync(int uid)
        {
            const int page = 1;
            const int rows = 100;
            const string endpoint = "/api/ZenSystem/GetOrderResultByUser";
            var request = new ZenBrightReportRequestDTO
            {
                Page = page,
                Rows = rows,
                Uid = uid
            };
            var response = await _zenBrightService.GetZenBrightReportAsync(endpoint, request);
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                var zenBrightReports = JsonConvert.DeserializeObject<ZenBrightReportResponseDTO>(json);
                if (zenBrightReports.Data == null || zenBrightReports.Data.Rows.Count == 0)
                    return null;
                return zenBrightReports.Data.Rows.Select(r =>
                {
                    return new TrainingReportQueryResultDTO
                    {
                        CourseId = 0,
                        TrainingItemId = 0,
                        TraineeId = uid,
                        JsonData = JsonConvert.SerializeObject(r.TestRecords),
                        ReportDate = r.OrderFinishDate
                    };
                });
            }
            return null;
        }
        public async Task<TrainingReportQueryResultDTO> GetTrainingReportByIdAsync(
            TrainingReportQueryByIdRequestDTO req)
        {
            var query = _context.TrainingReports.Include(tr => tr.Trainee)
                .Include(tr => tr.Course)
                .Include(tr => tr.TrainingItem)
                .Where(tr => tr.TrainingReportId == req.TrainingReportId);
            var report = await query.FirstOrDefaultAsync();
            if (report != null)
                return _mapper.Map<TrainingReportQueryResultDTO>(report);
            return null;
        }

        public async Task<TrainingReportQueryResultDTO> CreateTrainingReportAsync(TrainingReportCreateRequestDTO req)
        {
            var report = _mapper.Map<TrainingReport>(req);
            report.Sequence = 0;
            report.ReportDate = DateTime.Now;
            await _context.TrainingReports.AddAsync(report);
            _context.TrainingReports.Entry(report).State = EntityState.Added;
            await _context.SaveChangesAsync();
            return _mapper.Map<TrainingReportQueryResultDTO>(report);
        }
    }
}
